﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Toolkit.Web.Infastructure;
using Toolkit.Web.ExtensionMethods;
using System.Web;

namespace Toolkit.Web.ViewComponents.DataGrid
{
    public sealed class DataGridColumnBuilder<T> where T : class
    {
        public DataGridColumnBuilder(DataGridColumn<T> component)
        {
            if (component == null)
            {
                throw new ArgumentNullException("component");
            }

            Component = component;
        }

        public DataGridColumn<T> Component
        {
            get;
            private set;
        }

        #region Settings

        public DataGridColumnBuilder<T> HeaderHtmlAttributes(object attributes)
        {
            Component.HeaderHtmlAttributes.Merge(attributes, true);
            return this;
        }

        public DataGridColumnBuilder<T> HtmlAttributes(object attributes)
        {
            Component.HtmlAttributes.Merge(attributes, true);
            return this;
        }

        public DataGridColumnBuilder<T> Width(int width)
        {
            if (width < 0)
            {
                throw new ArgumentOutOfRangeException("width");
            }

            Component.Settings.Width = width;
            return this;
        }

        public DataGridColumnBuilder<T> Visibility(bool show)
        {
            Component.Settings.IsVisible = show;
            return this;
        }

        public DataGridColumnBuilder<T> Index(int? index)
        {
            Component.Settings.Index = index;
            return this;
        }

        public DataGridColumnBuilder<T> AlignHorizontally(string alignment)
        {
            Component.Settings.HorizontalAlignment = alignment;
            return this;
        }

        public DataGridColumnBuilder<T> WordWrap(bool enable)
        {
            Component.Settings.EnableWordWrap = enable;
            return this;
        }

        public DataGridColumnBuilder<T> Resizing(bool enable)
        {
            Component.Settings.EnableResizing = enable;
            return this;
        }

        public DataGridColumnBuilder<T> Sorting(bool enable)
        {
            return Sorting(enable, null, null, null);
        }

        public DataGridColumnBuilder<T> Sorting(string expression)
        {
            return Sorting(true, expression, null, null);
        }

        public DataGridColumnBuilder<T> Sorting(bool enable, string expression, bool? sorted, bool? descending)
        {
            Component.Settings.EnableSorting = enable;

            if (!string.IsNullOrEmpty(expression))
            {
                Component.Settings.SortExpression = new DataExpression(expression);
            }

            if (sorted.HasValue)
            {
                if (sorted.Value == true)
                {
                    Component.DataGrid.Settings.SortByColumnExpression = Component.Settings.SortExpression;

                    if (descending.HasValue)
                    {
                        Component.DataGrid.Settings.IsSortedInDescendingOrder = descending.Value;
                    }
                }
                else if (Component.DataGrid.Settings.SortByColumnExpression == Component.Settings.SortExpression)
                {
                    Component.DataGrid.Settings.SortByColumnExpression = null;
                    Component.DataGrid.Settings.IsSortedInDescendingOrder = false;
                }
            }

            return this;
        }

        public DataGridColumnBuilder<T> HidingAndShowing(bool enable)
        {
            Component.Settings.EnableHidingAndShowing = enable;
            return this;
        }

        public DataGridColumnBuilder<T> Menu(bool enable)
        {
            Component.Settings.EnableMenu = enable;
            return this;
        }

        #endregion Settings

        #region Templates

        public DataGridColumnBuilder<T> Label(string text)
        {
            Component.Label = HtmlStringExtensions.Create(HttpUtility.HtmlEncode(text));
            return this;
        }

        public DataGridColumnBuilder<T> Label(IHtmlString text)
        {
            Component.Label = text;
            return this;
        }

        public DataGridColumnBuilder<T> Header(Action<object, IViewComponentWriter> template)
        {
            Component.HeaderTemplate = new HtmlTemplate()
            {
                ActionTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> Header(Func<object, object> template)
        {
            Component.HeaderTemplate = new HtmlTemplate()
            {
                InlineTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> Footer(Action<object, IViewComponentWriter> template)
        {
            Component.FooterTemplate = new HtmlTemplate()
            {
                ActionTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> Footer(Func<object, object> template)
        {
            Component.FooterTemplate = new HtmlTemplate()
            {
                InlineTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> Body(Action<T, IViewComponentWriter> template)
        {
            Component.Template = new HtmlTemplate<T>()
            {
                ActionTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> Body(Func<T, object> template)
        {
            Component.Template = new HtmlTemplate<T>()
            {
                InlineTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> Editor(Action<T, IViewComponentWriter> template)
        {
            Component.EditorTemplate = new HtmlTemplate<T>()
            {
                ActionTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> Editor(Func<T, object> template)
        {
            Component.EditorTemplate = new HtmlTemplate<T>()
            {
                InlineTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> Filter(Action<DataGridColumnFilterFactory<T>> configurator)
        {
            if (configurator == null)
            {
                throw new ArgumentNullException("configurator");
            }

            Component.FilterFactory = configurator;
            return this;
        }

        public DataGridColumnBuilder<T> FilterSummary(Action<IReadOnlyDataGridColumn<T>, IViewComponentWriter> template)
        {
            Component.FilterSummaryTemplate = new HtmlTemplate<IReadOnlyDataGridColumn<T>>()
            {
                ActionTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> FilterSummary(Func<IReadOnlyDataGridColumn<T>, object> template)
        {
            Component.FilterSummaryTemplate = new HtmlTemplate<IReadOnlyDataGridColumn<T>>()
            {
                InlineTemplate = template
            };

            return this;
        }

        public DataGridColumnBuilder<T> AddMenuSection(Action<IReadOnlyDataGridColumn<T>, IViewComponentWriter> template)
        {
            if (template != null)
            {
                if (!Component.DataGrid.Menu.ColumnSpecificSectionTemplates.ContainsKey(Component.Identifier))
                {
                    Component.DataGrid.Menu.ColumnSpecificSectionTemplates[Component.Identifier] = new List<HtmlTemplate<IReadOnlyDataGridColumn<T>>>();
                }

                Component.DataGrid.Menu.ColumnSpecificSectionTemplates[Component.Identifier].Add(new HtmlTemplate<IReadOnlyDataGridColumn<T>>()
                {
                    ActionTemplate = template
                });
            }

            return this;
        }

        public DataGridColumnBuilder<T> AddMenuSection(Func<IReadOnlyDataGridColumn<T>, object> template)
        {
            if (template != null)
            {
                if (!Component.DataGrid.Menu.ColumnSpecificSectionTemplates.ContainsKey(Component.Identifier))
                {
                    Component.DataGrid.Menu.ColumnSpecificSectionTemplates[Component.Identifier] = new List<HtmlTemplate<IReadOnlyDataGridColumn<T>>>();
                }

                Component.DataGrid.Menu.ColumnSpecificSectionTemplates[Component.Identifier].Add(new HtmlTemplate<IReadOnlyDataGridColumn<T>>()
                {
                    InlineTemplate = template
                });
            }

            return this;
        }

        #endregion Templates
    }
}
